﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;

namespace WebFetch
{
    public class URL
    {
        #region Private Region
        Protocols protocal;
        string url;
        string host;
        string fileName;
        string pathWithOutFileName;
        string pathWithFileName;
        #endregion 

        #region Comment 
        //string lowalpha = @"[a-z]";
        //string hialpha = @"[A-Z]";
        //string alpha = String.Format(@"({0}|{1})", lowalpha, hialpha);
        //string digit = @"[0-9]";
        //string safe = @"(\$|-|_|\.|\+)";
        //string extra = @"(!|\*|'|\(|\)|,)";
        //string hex = String.Format(@"({0}|A|B|C|D|E|F|a|b|c|d|e|f)", digit);
        //string escape = String.Format(@"(%{0}{0})", hex);
        //string unreserved = String.Format(@"({0}|{1}|{2}|{3})", alpha, digit, safe, extra);
        //string uchar = String.Format(@"({0}|{1})", unreserved, escape);
        //string reserved = @"(;|/|\?|:|@|&|=)";
        //string xchar = String.Format(@"({0}|{1}|{2})", unreserved, reserved, escape);
        //string digits = String.Format(@"({0}+)", digit);

        //string alphadigit = String.Format(@"({0}|{1})", alpha, digit);
        //string domainlabel = String.Format(@"({0}|{0}({0}|-)*{0})", alphadigit);
        //string toplabel = String.Format(@"({0}|{0}({1}|-)*{1})", alpha, alphadigit);
        //string hostname = String.Format(@"(({0}\.)*{1})", domainlabel, toplabel);
        //string hostnumber = String.Format(@"{0}\.{0}\.{0}\.{0}", digits);
        //string host = String.Format(@"({0}|{1})", hostname, hostnumber);
        //string port = digits;
        //string hostport = String.Format(@"({0}(:{1}){{0,1}})", host, port);
        //string hsegment = String.Format(@"(({0}|;|:|@|&|=)*)", uchar);
        //string search = String.Format(@"(({0}|;|:|@|&|=)*)", uchar);
        //string hpath = String.Format(@"{0}(/{0})*", hsegment);
        //string httpurl = String.Format(@"http://{0}(/{1}(\?{2}){{0,1}}){{0,1}}", hostport, hpath, search);
        #endregion

        #region constructor
        public URL(string currentPath, string url)
        {

        }

        public URL(string url) 
        {
            this.url = url;
            Regex rHost = new Regex("http://([^/?]*){1}/?(.*)");
            Match m = rHost.Match(url);

            if (m.Success)
            {
                host = m.Groups[1].Value;
                pathWithFileName = RelatedPathToAbsolute(m.Groups[2].Value);

                Regex rFile = new Regex("(.*)/(.*)");
                Match mFile = rFile.Match((pathWithFileName));
                if (mFile.Success)
                {
                    fileName = mFile.Groups[2].Value;
                    pathWithOutFileName = RelatedPathToAbsolute(mFile.Groups[1].Value);
                    Regex rFile2 = new Regex("(.*)/(.*)\\?(.*)");
                    Match mFile2 = rFile2.Match((pathWithFileName));
                    if (mFile2.Success)
                    {
                        fileName = mFile2.Groups[2].Value;
                        pathWithOutFileName = RelatedPathToAbsolute(mFile2.Groups[1].Value);
                    }

                    if (IsKnowFileType(fileName) == false)
                    {
                        fileName = "index.html";
                        pathWithOutFileName = pathWithFileName;
                        pathWithFileName = HtmlParserHelper.ConcatURL(pathWithOutFileName, fileName);
                    }
                    else
                        pathWithFileName = HtmlParserHelper.ConcatURL(pathWithOutFileName, fileName);

                    return;
                }

                Regex rFile3 = new Regex("(.*)\\?(.*)");
                Match mFile3 = rFile3.Match((pathWithFileName));
                if(mFile3.Success)
                {
                    fileName = mFile3.Groups[1].Value;
                    pathWithOutFileName = "";
                    pathWithFileName = fileName;
                    
                    return;
                }

                //else
                {
                    fileName = "index.html";
                    pathWithOutFileName = pathWithFileName;
                    pathWithFileName = HtmlParserHelper.ConcatURL(pathWithOutFileName, fileName);
                }
            }
        }
        #endregion

        #region Public Property
        public string Url
        {
            get { return url; }
            set { url = value; }
        }

        public string PathWithFileName
        {
            get { return pathWithFileName; }
            set { pathWithFileName = value; }
        }

        public string PathWithOutFileName
        {
            get { return pathWithOutFileName; }
            set { pathWithOutFileName = value; }
        }

        public string HostName
        {
            get { return host; }
            set { host = value; }
        }

        public string FileName
        {
            get { return fileName; }
            set { fileName = value; }
        }

        public string CurrentPath
        {
            get { return "http://" + host + "/" + pathWithOutFileName; }
        }

        /// <summary>
        /// Domain Name
        /// </summary>
        public string DomainName
        {
            get
            {

                string[] names = HostName.Split('.');
                string domainNameTemp = "";

                for (int i = 1; i < names.Length-1; i++)
                {
                    domainNameTemp += names[i]+".";
                }
                domainNameTemp += names[names.Length - 1];
                return domainNameTemp;

                //Regex rType = new Regex("(.*)\\.(.*)\\.(.*)");

                //if (rType.IsMatch(HostName))
                //{
                //    Match m = rType.Match(HostName);
                //    return m.Groups[2].ToString() + "." + m.Groups[3].ToString();
                //}
                //return null;
            }
        }

        #endregion


        private void parseUrl(string url)
        {

        }

        private string RelatedPathToAbsolute(string path)
        {
            string[] dirName = path.Split('/');

            Stack<string> validatedPath = new Stack<string>();
            if (dirName.Length <= 1)
                return path;

            foreach (string name in dirName)
            {
                if (name == "..")
                {
                    if (validatedPath.Count > 0) //Bug1 "too many ..", when stack is empty, the error is occured.
                        validatedPath.Pop();
                    continue;
                }
                else if (name == ".")
                    continue;
                else if (name == "")
                    continue;
                validatedPath.Push(name);
            }
            string filterPath = "";

            string[] paths = validatedPath.ToArray();
            Array.Reverse(paths);

            foreach(string name in paths)
            {
                filterPath += "/" + name ;
            }

            return filterPath.Substring(1);
        }

        private bool IsKnowFileType(string extension)
        {
            Regex rType = new Regex("(.*)\\.(.*)");

            Match rMatch = rType.Match(extension);
            if (rMatch.Success == false)
            {
                return false;
            }
            else
            {
                switch (rMatch.Groups[2].Value)
                {
                    case "bmp":
                    case "dib":
                    case "jpg":
                    case "jpeg":
                    case "jpe":
                    case "jfif":
                    case "gif":
                    case "tif":
                    case "tiff":
                    case "png":
                    case "mp3":
                    case "html":
                    case "htm":
                    case "shtml":
                    case "xml":
                    case "php":
                    case "phpx":
                    case "clsp":
                        return true;
                }
            }
            return false;
        }
    }

    public enum Protocols
    {
        /// <summary>
        /// 
        /// </summary>
        http,
        /// <summary>
        /// 
        /// </summary>
        https,
        /// <summary>
        /// 
        /// </summary>
        ftp,
        /// <summary>
        /// 
        /// </summary>
        svn,
        /// <summary>
        /// 
        /// </summary>
        git,
    }


}
